package top.codechap.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @author CodeChap
 * @date 2021-06-17 16:44
 * @description LogAspects
 *
 * @Aspect 告诉Spring,这是一个切面类
 */
@Component
@Aspect  //@Aspect标注这个类是一个切面
public class LogAspects {

    @Pointcut("execution(* top.codechap.aop.*.*(..))")
//    @Pointcut("execution(public int top.codechap.aop.MathCalculator.*(..))")
    public void pointCut() {}

    //注解后接 切入点表达式(指定在哪个方法切入)
    // execution()是最常用的切点函数，其语法如下所示：
    //        整个表达式可以分为五个部分：
    //        1、execution(): 表达式主体。
    //        2、第一个*号：表示返回类型， *号表示所有的类型。
    //        3、包名：表示需要拦截的包名，后面的两个句点表示当前包和当前包的所有子包，top.codechap.aop包、子孙包下所有类的方法。
    //        4、第二个*号：表示类名，*号表示所有的类。
    //        5、*(..):最后这个星号表示方法名，*号表示所有的方法，后面括弧里面表示方法的参数，两个句点表示任何参数
//    @Before("top.codechap.aop.MathCalculator.div(int,int)")
    @Before("pointCut()")
    public void logStart(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();   //获取切入点处的方法的参数
        System.out.println(joinPoint.getSignature().getName() + "运行 ... 参数列表是{" + Arrays.asList(args) +"}");
    }

    @After("pointCut()")
    public void logEnd(JoinPoint joinPoint) {
        System.out.println(joinPoint.getSignature().getName() + "结束");
    }

    //returning表示使用后面的result来接收方法的返回值,并作为形参传递给logReturn()方法
    @AfterReturning(value = "pointCut()",returning = "result")
    public void logReturn(JoinPoint joinPoint, Object result) { //JointPoint必须作为方法的第一个形参
        System.out.println(""+joinPoint.getSignature().getName()+"正常返回 ... 运行结果是 : {" + result + "}");
    }

    //throwing表示使用后面的exception来接收方法的返回值,并作为形参传递给logException()方法
    @AfterThrowing(value = "pointCut()", throwing = "exception")
    public void logException(JoinPoint joinPoint, Exception exception) {
        System.out.println(""+joinPoint.getSignature().getName() +"异常 ... 异常信息 : {" + exception + "}");
    }
}
